<template>
  <div style="position: relative;">
    <div id="container" style="width: 100%; height: 800px;"></div>
    <div id="statsPos" v-show="statsSwitch"></div>

    <div class="tools">
      <a-card class="box-card">
        <div slot="title" class="clearfix">
          <span>风机:{{info.modelId}}</span>
        </div>
        <a-button @click="starts(0)">001-开关</a-button>
        <a-button @click="starts(1)">002-开关</a-button>
        <a-button @click="status(7)">008-故障恢复</a-button>
        <a-button @click="status(4)">004-故障恢复</a-button>
        <a-button @click="overallView()">全景俯视</a-button>
        <a-button @click="resetAngle()">视图复位</a-button>
        <a-button @click="gotolink('Alone')">路由跳转</a-button>
        <a-button @click="seaSwitch = !seaSwitch">海面效果</a-button>
        <a-button @click="statsSwitch = !statsSwitch">帧率监视</a-button>
        <a-button @click="sceneChange()">场景</a-button>
      </a-card>
    </div>

  </div>
</template>
<script>
import * as Three from 'three'
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { Water } from 'three/examples/jsm/objects/Water';
import { Sky } from 'three/examples/jsm/objects/Sky.js';

import Stats from "three/examples/jsm/libs/stats.module";

let water, sun, mouse, raycaster

export default {
  data () {
    return {
      height: null,
      camera: null,
      scene: null,
      renderer: null,
      controls: null,
      windmill: [{
        lat:0,
        log:0,
        start: true,
        obj:null,
        info:{
          modelId:'001',
          status: 0
        }
      },{
        lat:100,
        log:100,
        start: true,
        obj:null,
        info:{
          modelId:'002',
          status: 0
        }
      },{
        lat:200,
        log:200,
        start: true,
        obj:null,
        info:{
          modelId:'003',
          status: 0
        }
      },{
        lat:-100,
        log:100,
        start: true,
        obj:null,
        info:{
          modelId:'004',
          status: 0
        }
      },{
        lat:-200,
        log:200,
        start: true,
        obj:null,
        info:{
          modelId:'005',
          status: 1
        }
      },{
        lat:-100,
        log:-100,
        start: true,
        obj:null,
        info:{
          modelId:'006',
          status: 0
        }
      },{
        lat:-200,
        log:-200,
        start: true,
        obj:null,
        info:{
          modelId:'007',
          status: 0
        }
      },{
        lat:100,
        log:-100,
        start: false,
        obj:null,
        info:{
          modelId:'008',
          status: 2
        }
      },{
        lat:200,
        log:-200,
        start: true,
        obj:null,
        info:{
          modelId:'009',
          status: 0
        }
      },{
        lat:300,
        log:-300,
        start: true,
        obj:null,
        info:{
          modelId:'010',
          status: 0
        }
      },{
        lat:350,
        log:-350,
        start: true,
        obj:null,
        info:{
          modelId:'011',
          status: 0
        }
      },{
        lat:400,
        log:-400,
        start: true,
        obj:null,
        info:{
          modelId:'012',
          status: 0
        }
      },{
        lat:450,
        log:-450,
        start: true,
        obj:null,
        info:{
          modelId:'012',
          status: 0
        }
      },{
        lat:500,
        log:-500,
        start: true,
        obj:null,
        info:{
          modelId:'013',
          status: 0
        }
      }],
      info:{
        modelId:''
      },
      seaSwitch: true,
      statsSwitch: true,
      timeIndex: null
    }
  },
  beforeDestroy(){
    cancelAnimationFrame(this.timeIndex);
  },
  methods: {
    getHeight() {
      this.height = window.innerHeight + "px";
    },
    init() {
      let container = document.getElementById('container')

      this.scene = new Three.Scene()

      this.camera = new Three.PerspectiveCamera(70, container.clientWidth / container.clientHeight, 0.01, 100000)
      this.camera.position.set(40, 50, 100)

      const gltfLoader = new GLTFLoader();

      let logoTexture = new Three.Texture();
      const imgLoader = new Three.ImageLoader();
      imgLoader.load(this.baseUrl + "/static/models/logo_m.png",function(img)
      {
        logoTexture.image = img;
        logoTexture.needsUpdate = true;
      });

      gltfLoader.load(this.baseUrl + '/static/models/windmill.gltf', (obj) => {
        obj.scene.children[0].children[2].material = new Three.MeshLambertMaterial({
          side: Three.DoubleSide,
          transparent: true,
          opacity: 1,
          map: logoTexture,
          alphaTest:0.1,
          shininess:10,
        })

        obj.scene.children[0].children[3].material = new Three.MeshLambertMaterial({
          side: Three.DoubleSide,
          transparent: true,
          opacity: 1,
          map: logoTexture,
          alphaTest:0.1,
          shininess:10,
        })

        for(let i = 0; i<this.windmill.length; i++){
          this.windmill[i].obj = obj.scene.clone()
          this.windmill[i].obj.children[0].children[0].children[0].material = obj.scene.children[0].children[0].children[0].material.clone()
          this.windmill[i].obj.position.set(this.windmill[i].lat, 0, this.windmill[i].log)
          this.scene.add(this.windmill[i].obj)
        }

      });

      let geometry = new Three.BoxGeometry( 60, 100, 20 );
      let material = new Three.MeshBasicMaterial( {opacity: 0, transparent: true, wireframe:true} );

      for(let i = 0; i<this.windmill.length; i++){
        let cube = new Three.Mesh( geometry, material );
        cube.position.set(this.windmill[i].lat, 50, this.windmill[i].log)
        cube.name = this.windmill[i].info.modelId
        this.scene.add( cube );
      }

      this.renderer = new Three.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true})
      this.renderer.setClearColor(0xb9d3ff, 1);
      this.renderer.setPixelRatio( window.devicePixelRatio );
      this.renderer.setSize(container.clientWidth, container.clientHeight)
      this.renderer.domElement.style.outline = "none"
      container.appendChild(this.renderer.domElement)

      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.maxPolarAngle = Math.PI * 0.495;
      this.controls.target.set( 0, 50, 0 );
      this.controls.minDistance = 40.0;
      this.controls.maxDistance = 700.0;
      this.controls.update();

      const ambient = new Three.AmbientLight(0x444444, 2.5);
      this.scene.add(ambient);

      const pointLight = new Three.PointLight(0xffffff, 0.5);
      pointLight.position.set(0, 400, 800);
      this.scene.add(pointLight);
      var pointLightHelper = new Three.PointLightHelper( pointLight, 10 );
      //   this.scene.add( pointLightHelper );

      window.addEventListener(
          "resize",
          () => {
            this.renderer.setSize(container.clientWidth, container.clientHeight);
            // this.camera.aspect = window.innerWidth/window.innerHeight;
            this.camera.aspect = container.clientWidth/container.clientHeight;
            this.camera.updateProjectionMatrix ();
          },
          false
      );

      raycaster = new Three.Raycaster();
      mouse = new Three.Vector2();

      window.addEventListener("click", this.onMouseClick, false);
    },
    onMouseClick(event) {
      mouse.x = (event.offsetX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.offsetY / window.innerHeight) * 2 + 1;
      raycaster.setFromCamera(mouse, this.camera);
      let intersects = raycaster.intersectObjects(this.scene.children, true);

      intersects = intersects.filter((intersect) => {
        return !(intersects.object instanceof Three.GridHelper) &&
            intersect.object.name !== 'water' &&
            intersect.object.name !== 'plane' &&
            intersect.object.name !== 'sky'
      });
      this.info.modelId = intersects[0].object.name
    },
    water() {
      const waterGeometry = new Three.PlaneGeometry( 10000, 10000 );

      water = new Water(
          waterGeometry,
          {
            textureWidth: 512,
            textureHeight: 512,
            waterNormals: new Three.TextureLoader().load(this.baseUrl + '/static/models/waternormals.jpg', function ( texture ) {

              texture.wrapS = texture.wrapT = Three.RepeatWrapping;

            } ),
            sunDirection: new Three.Vector3(),
            sunColor: 0xffffff,
            waterColor: 0x2582c4,
            distortionScale: 3.7,
            fog: this.scene.fog !== undefined
          }
      );

      water.name = "water"
      water.rotation.x = - Math.PI / 2;
      this.scene.add( water );
    },
    plane() {
      var waterMap = new Three.TextureLoader().load(this.baseUrl + '/static/models/watermap.jpg');
      waterMap.repeat.set(100,100)
      waterMap.wrapS = waterMap.wrapT = Three.RepeatWrapping;//MirroredRepeatWrapping镜像平铺 RepeatWrapping重复平铺
      const planeGeometry = new Three.PlaneGeometry( 10000, 10000 );
      const planeMaterial = new Three.MeshBasicMaterial( {side: Three.DoubleSide, map: waterMap} );
      const plane = new Three.Mesh( planeGeometry, planeMaterial );
      plane.name = "plane"
      plane.rotation.x = - Math.PI / 2;
      this.scene.add( plane );
    },
    sky() {
      sun = new Three.Vector3();

      const sky = new Sky();
      sky.name = "sky"
      sky.scale.setScalar( 10000 );
      this.scene.add( sky );

      const parameters = {
        elevation: 2,
        azimuth: 0
      };

      const phi = Three.MathUtils.degToRad( 60 - parameters.elevation );
      const theta = Three.MathUtils.degToRad( parameters.azimuth );

      sun.setFromSphericalCoords( 1, phi, theta );

      sky.material.uniforms[ 'sunPosition' ].value.copy( sun );
      water.material.uniforms[ 'sunDirection' ].value.copy( sun ).normalize();

    },
    animate() {
      this.timeIndex = requestAnimationFrame(this.animate)
      for(var i = 0; i<this.windmill.length; i++){
        if(this.windmill[i].start == true && this.windmill[i].obj !== null){
          this.windmill[i].obj.children[0].children[0].rotation.z += 0.005
        }
        if(this.windmill[i].info.status == 0 && this.windmill[i].obj !== null){
          this.windmill[i].obj.children[0].children[0].children[0].material.color.set("#ffffff")
        }else if(this.windmill[i].info.status == 1 && this.windmill[i].obj !== null){
          this.windmill[i].obj.children[0].children[0].children[0].material.color.set("#efdf6d")
        }else if(this.windmill[i].info.status == 2 && this.windmill[i].obj !== null){
          this.windmill[i].start = false
          this.windmill[i].obj.children[0].children[0].children[0].material.color.set("#e7425d")
        }
      }
      this.stats.update()
      this.render()
    },
    render() {
      if(this.seaSwitch == true){
        water.material.uniforms[ 'time' ].value += 1.0 / 60.0;
      }
      this.renderer.render(this.scene, this.camera)
    },
    starts(index) {
      this.windmill[index].start = !this.windmill[index].start
    },
    status(index) {
      this.windmill[index].info.status = 0
      this.windmill[index].start = true
    },
    overallView() {
      this.camera.position.set(0, 367, 488)
      this.camera.lookAt(0, 50, 0)
      this.controls.target.set( 0, 50, 0 );
    },
    resetAngle() {
      this.camera.position.set(40, 50, 100)
      this.camera.lookAt(0, 50, 0)
      this.controls.target.set( 0, 50, 0 );
    },
    gotolink(path){
      this.$router.replace(path)
    },
    initStats() {
      this.stats = new Stats();
      this.stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
      let statsPos = document.getElementById("statsPos")
      statsPos.appendChild(this.stats.domElement);
    },
    sceneChange() {
      let allChildren = this.scene.children;
      for(let i in allChildren) {
        if(allChildren[i].name == 'water') {
          this.scene.remove(allChildren[i]);
        }
      }
      console.log('this.scene',this.scene);
      this.plane()
    }
  },
  created() {
    window.addEventListener("resize", this.getHeight);
    this.getHeight();
  },
  mounted () {
    this.init()
    this.initStats()
    this.water()
    this.sky()
    this.animate()
  }
}

</script>

<style lang="less" scoped>
#container {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  position: relative;
  z-index: 1;
}

.tools{
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 3;
}

/deep/#statsPos{
  & > div{
    position: absolute !important;
    right: 0;
    left: inherit !important;
  }
}

.box-card{
  .ant-btn + .ant-btn {
    margin-left: 10px;
  }
}
</style>
